package ophiux.common.parse.xml;

import java.util.ArrayList;
import java.util.List;

import ophiux.api.sdk.OphiuxApiException;
import ophiux.common.parse.EntityConverter;
import ophiux.common.parse.IConvert;
import ophiux.common.parse.Reader;
import ophiux.common.parse.Writer;
import ophiux.common.utils.XMLUtil;

import org.w3c.dom.Element;

public class XmlConverter implements IConvert {

	@Override
	public <T> T toEntity(Class<T> clzz, String dataSource)
			throws OphiuxApiException {
		Element rootElement = XMLUtil.getDocmentElement(dataSource);
		return buildEntityByXML(clzz, rootElement);
	}

	public <T> T buildEntityByXML(Class<T> clzz,final Element rootElement) throws OphiuxApiException{
		Reader xmlReader = new Reader() {
			@Override
			public boolean isExistNode(String tagNames) {
				Object value = XMLUtil.getChildElement(rootElement, tagNames);
				
				return value != null;
			}
			
			
			@Override
			public Object getNodeValue(String tagNames) {
				Object value = XMLUtil.getElementValue(rootElement, tagNames);
				
				return value;
			}
			
			@Override
			public Object getNodeObject(String tagName, Class<?> subType) throws OphiuxApiException {
				Element childElement = XMLUtil.getChildElement(rootElement, tagName);
				if(childElement != null){
					return buildEntityByXML(subType, childElement);
				}
				return null; 
			}
			
			@Override
			public List<?> getNodeListObject(String parentName, String tagNames,
					Class<?> subType) throws OphiuxApiException {
				List dataList = new ArrayList<Object>();
				Element parentElement = XMLUtil.getChildElement(rootElement, parentName);
				if(parentElement == null){
					return null;
				}
				List<Element> currentElementList = XMLUtil.getChildElements(parentElement, tagNames);
				for(Element element : currentElementList){
					Object obj = XMLUtil.getElementValue(element);
					try {
						if(String.class.isAssignableFrom(subType)){
							
						}else if(Long.class.isAssignableFrom(subType)){
							
						}else if(Integer.class.isAssignableFrom(subType)){
							
						}else if(Boolean.class.isAssignableFrom(subType)){
							
						}else if(List.class.isAssignableFrom(subType)){
							
						}else{
							obj = buildEntityByXML(subType,element);
						}
						dataList.add(obj);
					} catch (IllegalArgumentException e) {
						e.printStackTrace();
						throw new OphiuxApiException(e);
					}
				}
				return dataList;
			}
		};
		return EntityConverter.convert(clzz, xmlReader);
	}
	
	public static void main(String[] args) {
		XmlConverter test = new XmlConverter();
	}

	@Override
	public <T> String entityToString(T obj) throws OphiuxApiException {
		return parseEntityToString(obj);
	}
	
	public <T> String parseEntityToString(T obj) throws OphiuxApiException{
		String targetStr = "";
		Writer writer = new Writer() {
			
			@Override
			public String writerFromString(Object value, String nodeName) throws OphiuxApiException {
				String str = "";
				if(value == null || value.equals("null")){
					value = "";
				}
				str += "<"+nodeName+">"+value+"</"+nodeName+">";
				return str;
			}
			
			@Override
			public String writerFromObject(Object obj,String nodeName) throws OphiuxApiException{
				String str = "";
				if(obj != null){
					String objStr = parseEntityToString(obj);
					str += "<"+nodeName+">"+objStr+"</"+nodeName+">";
				}else{
					str += "<"+nodeName+">"+""+"</"+nodeName+">";
				}
				
				return str;
			}

			@Override
			public <T> String writerFromArray(List<T> valueList,
					String parentNodeName, String nodeName) throws OphiuxApiException{
				String str = "";
				String listStr = "";
				if(valueList != null && valueList.size() != 0){
					for(T obj : valueList){
						String objStr = "";
						objStr += "<"+nodeName+">"+parseEntityToString(obj)+"</"+nodeName+">";
						listStr += objStr;
					}
				}
				str += "<"+parentNodeName+">"+listStr+"</"+parentNodeName+">";
				return str;
			}
			
		};
		
		targetStr = EntityConverter.writerToString(obj, writer);
		return targetStr;
	}
	
}
